#region (c) 2009 Rinat Abdullin

// Copyright (c) Rinat Abdullin
// All Rights Reserved
// Site: http://abdullin.com

#endregion

using System;
using System.Linq;
using System.Reflection;
using Jayrock.Json;
using Jayrock.Json.Conversion;
using Jayrock.Json.Conversion.Converters;

namespace NCouch.Json
{
	sealed class FieldExporter : ExporterBase
	{
		readonly FieldInfo[] _fields;
		// Methods
		public FieldExporter(Type inputType)
			: base(inputType)
		{
			_fields = inputType.GetFields().Where(f => !f.IsStatic).ToArray();
		}

		protected override void ExportValue(ExportContext context, object value, JsonWriter writer)
		{
			if (_fields.Length == 0)
			{
				writer.WriteString(value.ToString());
			}
			else
			{
				ObjectReferenceTracker tracker = null;
				try
				{
					writer.WriteStartObject();
					foreach (var property in _fields)
					{
						object propertyValue = property.GetValue(value);
						if (!JsonNull.LogicallyEquals(propertyValue))
						{
							writer.WriteMember(property.Name);
							if (tracker == null)
							{
								tracker = TrackObject(context, value);
							}
							context.Export(propertyValue, writer);
						}
					}
					writer.WriteMember("_type");
					context.Export(InputType.Name, writer);
					writer.WriteEndObject();
				}
				finally
				{
					if (tracker != null)
					{
						tracker.Pop(value);
					}
				}
			}
		}


		static ObjectReferenceTracker TrackObject(ExportContext context, object value)
		{
			Type key = typeof(FieldExporter);
			var tracker = (ObjectReferenceTracker) context.Items[key];
			if (tracker == null)
			{
				tracker = new ObjectReferenceTracker();
				context.Items.Add(key, tracker);
			}
			tracker.PushNew(value);
			return tracker;
		}

		// Nested Types
	}
}